/**
 * 
 * @author  phoenics@126.com
 * @version v.0.1
 * @date  2018年3月14日 下午2:06:56 
 * 
 */
package phoenics.upservice.service;

import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPrivateKey;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Optional;
import java.util.UUID;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultJwtBuilder;
import io.jsonwebtoken.impl.DefaultJwtParser;
import phoenics.upservice.auth.JwtAuthentication;
import phoenics.upservice.entity.User;
import phoenics.upservice.repository.UserRepo;

import static java.util.Optional.empty; 
import static java.util.Collections.emptyList;
/**
 *
 */
@Service  
public class JwtService {
	private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JwtService.class);
	@Value("${jwt.key.store}") private String keystore;  
	    @Value("${jwt.key.pass}") private String keypass;  
	    @Value("${jwt.key.alias}") private String keyalias;  
	    @Value("${jwt.cert}") private String cert;  
	  
	    private UserRepo userRepo;  
	    private PrivateKey privateKey;  
	    private PublicKey publicKey;  
	  
	    public JwtService(@Autowired UserRepo userRepo){  
	        this.userRepo = userRepo;  
	    }  
	  
	    @PostConstruct  
	    private void init() throws Exception {  
	        char[] pass = keypass.toCharArray();  
	        KeyStore from = KeyStore.getInstance("JKS", "SUN");  
	        //ClassPathResource cp=new ClassPathResource(keystore);
	        from.load(new ClassPathResource(keystore).getInputStream(), pass);  
	        logger.info("2   {}",from.getKey(keyalias, pass).getAlgorithm());
	        //privateKey = (ECPrivateKey) from.getKey(keyalias, pass);  
	        privateKey = (PrivateKey) from.getKey(keyalias, pass);  
	  
	        CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");  
	        X509Certificate x509Cert = (X509Certificate) certificatefactory.generateCertificate(new ClassPathResource(cert).getInputStream());  
	        publicKey = x509Cert.getPublicKey();  
	    }  
	  
	    public String generate(User user){  
	        return new DefaultJwtBuilder()  
	                .setId(UUID.randomUUID().toString())  
	                .setSubject(user.getMobile())  
	                .setExpiration(Date.from(ZonedDateTime.now().plusWeeks(1).toInstant()))  
	              //  .signWith(SignatureAlgorithm.ES256, privateKey).compact();  
	                .signWith(SignatureAlgorithm.RS256, privateKey).compact();  
	    }  
	  
	    public Optional<JwtAuthentication> parse(String token){  
	        try {  
	            Jws<Claims> jws = new DefaultJwtParser().setSigningKey(publicKey).parseClaimsJws(token);  
	            Claims claims = jws.getBody();  
	            return userRepo.findMobileCached(claims.getSubject()).map(u -> new JwtAuthentication(u, token, claims));  
	        }catch (Exception e){  
	        	logger.error("failed to parse jwt token {}", token, e);  
	        }  
	        return empty();  
	    }  
	    public Optional<Claims> parse4Claims(String token){  
	    	Optional<Claims> claims =empty();  
	    	try {  
	            Jws<Claims> jws = new DefaultJwtParser().setSigningKey(publicKey).parseClaimsJws(token);  
	            claims =Optional.of(jws.getBody());
	        }catch (Exception e){  
	        	logger.error("failed to parse jwt token {}", token, e);  
	        }  
	        return claims;
	    }
}
